/***************************************************************
 *  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
 *  All rights reserved.
 *
 *  This file is part of the GroupMe! Project. Source code of 
 *  this project is closed and redistribution of this code is
 *  prohibited. 
 *  
 *  Contact: http://www.groupme.net
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package net.groupme.model.dao.mem;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import net.groupme.exceptions.DeleteFailedException;
import net.groupme.exceptions.GroupVisualizationException;
import net.groupme.exceptions.InsertFailedException;
import net.groupme.exceptions.UpdateFailedException;
import net.groupme.exceptions.UserNotExistingException;
import net.groupme.model.Group;
import net.groupme.model.GroupVisualization;
import net.groupme.model.MODEL_CONSTANTS;
import net.groupme.model.ObjectFactory;
import net.groupme.model.Resource;
import net.groupme.model.ResourceVisualization;
import net.groupme.model.Tag;
import net.groupme.model.User;
import net.groupme.model.dao.DATABASE_CONSTANTS;
import net.groupme.model.dao.GroupDAO;

import org.apache.log4j.Logger;

/**
 * created on 13.02.2008
 * 
 * This class is an In-Memory-DAO implementation of a {@link GroupDAO}. Hence,
 * nothing is stored within a database. <b>ATTENTION:</b> Functions that
 * require additional infos like {@link Resource#getTags(User)} are not
 * implemented!!
 * 
 * @author Mischa Frank, <a
 *         href="mailto:code@planetfrank.net">code@planetfrank.net</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.10 $ $Date: 2008-11-07 16:24:06 $
 */

public class GroupDAOMemImpl extends ResourceDAOMemImpl implements GroupDAO {

	private Collection<Resource> resources = null;
	private User owner = null;
	private Collection<User> subscriber = null;
	private GroupVisualization groupVisu = null;

	private static final Logger log = Logger.getLogger(GroupDAOMemImpl.class);

	/**
	 * Creates a new GroupDAOMemImpl instance.
	 * 
	 * @param id
	 * @param name
	 * @param description
	 * @param url
	 * @param type
	 * @param owner
	 */
	public GroupDAOMemImpl(String id, String name, String description) {
		super(id, name, description, null, MODEL_CONSTANTS.RESOURCE_TYPE_GROUP);
		this.resources = new HashSet<Resource>();
		this.subscriber = new HashSet<User>();
		try {
			this.groupVisu = ObjectFactory.getInMemoryGroupVisualization(this);
		} catch (InsertFailedException e) {
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#addResource(net.groupme.model.Resource)
	 */
	public void addResource(Resource resource) throws InsertFailedException {
		this.resources.add(resource);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#addUser(java.lang.String,
	 *      net.groupme.model.User)
	 */
	public void addUser(String role, User user) throws InsertFailedException {
		if (DATABASE_CONSTANTS.User_ROLE_OWNER.equals(role)) {
			this.owner = user;
		} else if (DATABASE_CONSTANTS.User_ROLE_SUBSCRIBER.equals(role)) {
			this.subscriber.add(user);
		} else
			throw new InsertFailedException("Role: " + role
					+ " is not supported.");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#addVisualization(net.groupme.model.GroupVisualization,
	 *      net.groupme.model.User)
	 */
	public void addVisualization(GroupVisualization groupVisualization,
			User user) throws InsertFailedException {
		this.groupVisu = groupVisualization;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getActualGroupVisualization(java.lang.String)
	 */
	public GroupVisualization getActualGroupVisualization(String userID)
			throws GroupVisualizationException {
		return this.groupVisu;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getResources()
	 */
	public Collection<Resource> getResources() {
		return this.resources;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getStandardVisualization()
	 */
	public GroupVisualization getStandardVisualization() {
		return this.groupVisu;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getUsers()
	 */
	public Collection<User> getUsers() {
		Collection<User> tmpUsers = new HashSet<User>();
		tmpUsers = subscriber;
		tmpUsers.add(owner);
		return tmpUsers;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getUsers(java.lang.String)
	 */
	public Collection<User> getUsers(String role) {
		if (DATABASE_CONSTANTS.User_ROLE_OWNER.equals(role)) {
			Collection<User> tmpUsers = new HashSet<User>();
			tmpUsers.add(owner);
			return tmpUsers;
		} else if (DATABASE_CONSTANTS.User_ROLE_SUBSCRIBER.equals(role)) {
			return subscriber;
		}
		return new HashSet<User>();
	}

	/* (non-Javadoc)
	 * @see net.groupme.model.Group#getCreators()
	 */
	public Collection<User> getCreators() {
		Collection<User> creators = new HashSet<User>();
		creators.addAll(getUsers(MODEL_CONSTANTS.ROLE_OWNER));
		creators.addAll(getUsers(MODEL_CONSTANTS.ROLE_MODERATOR));
		return creators;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getVisualizations()
	 */
	public Collection<GroupVisualization> getVisualizations() {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#getVisualizations(net.groupme.model.User)
	 */
	public Collection<GroupVisualization> getVisualizations(User user) {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#removeResource(net.groupme.model.Resource)
	 */
	public void removeResource(Resource resource) throws DeleteFailedException {
		if (!this.resources.remove(resource))
			throw new DeleteFailedException("Resource " + resource.getId()
					+ " could not be removed from Group.");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#removeUser(net.groupme.model.User)
	 */
	public void removeUser(User user) throws DeleteFailedException {
		if (owner.equals(user))
			throw new DeleteFailedException("User " + user.getUserName()
					+ " is the owner of this group and cannot be removed.");
		else if (subscriber.contains(user)) {
			subscriber.remove(user);
		} else
			throw new DeleteFailedException("User " + user.getUserName()
					+ " wasn't found.");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#removeVisualization(net.groupme.model.GroupVisualization,
	 *      net.groupme.model.User)
	 */
	public void removeVisualization(GroupVisualization groupVisualization,
			User user) throws DeleteFailedException {
		// TODO Auto-generated method stub

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.groupme.model.Group#setStandardVisualization(net.groupme.model.GroupVisualization)
	 */
	public void setStandardVisualization(GroupVisualization groupVisualization) {
		this.groupVisu = groupVisualization;
	}

	public void saveGrouptoDB() {

		try {

			// Create a Group for the DB
			Group group = ObjectFactory.createGroup(this.getName(), this
					.getDescription());
			
			// Get the user which creates the Group
			User user = ObjectFactory.getUser(new Integer(owner.getId()));
			
			// add the User to the Group as Owner
			user.addGroup(group, MODEL_CONSTANTS.ROLE_OWNER);
			
			// Create a groupvisualisation for the Group
			GroupVisualization groupVisuDB = ObjectFactory
					.createGroupVisualization();
			
			groupVisuDB.setDescription("It is maintained by "
					+ user.getUserName());
			
			groupVisuDB.setGroup(group);
			log.info("Added Group to Group visualisation");
			groupVisuDB.setLabel(this.groupVisu.getLabel());
			log.info("Set Groupvisualisation Label to:"
					+ this.groupVisu.getLabel());
			groupVisuDB.setName("Visualisation of " + this.groupVisu.getName());
			log.info("Set Groupvisualisation Name to:"
					+ this.groupVisu.getName());
			group.setStandardVisualization(groupVisuDB);
			group.addVisualization(groupVisuDB, user);
	
			
			//tags zu der gruppe hinzufügen
			Iterator<Tag> iterGruppenTags = this.getTags().iterator();
			while (iterGruppenTags.hasNext()){
				Tag gruppenTag = iterGruppenTags.next();
				Tag gruppenTagDB = ObjectFactory.getTagForKeyword(gruppenTag.getKeyword());
				group.addTag(user, gruppenTagDB);
			}
			
			
			
			// add all Resources to the Group
			int[] resVisuZuordnung = new int[this.resources.size()];
			Iterator<Resource> iter = this.resources.iterator();
			int i = 0;
			while (iter.hasNext()) {
				Resource r1 = iter.next();
				Resource resource = ObjectFactory.createResource(r1.getName(),
						r1.getDescription(), r1.getType(), r1.getURL());
				
				resVisuZuordnung[i] = new Integer(resource.getId());
				group.addResource(resource);
				i++;
				
				//alle tags zu den resourcen hinzufügen
				Iterator<Tag> iterTag = r1.getTags().iterator();
				while (iterTag.hasNext()){
					Tag tag = iterTag.next();
					Tag tagDB = ObjectFactory.getTagForKeyword(tag.getKeyword());
					resource.addTag(user, tagDB, group);
					
				}
			}
			// Speichern der Resource Visualisierungen in die DB

			Iterator<ResourceVisualization> iterForResVisu = this.groupVisu
					.getResourceVisualizations().iterator();
			i = 0;
			while (iterForResVisu.hasNext()) {
				ResourceVisualization resVisu = iterForResVisu.next();
				ResourceVisualization resVisuDB = ObjectFactory
						.createResourceVisualization(groupVisuDB.getId(),
								resVisuZuordnung[i] + "", resVisu
										.getPositionX(),
								resVisu.getPositionY(), resVisu.getWidth(),
								resVisu.getHeight());
				i++;
			}

		} catch (InsertFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UserNotExistingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UpdateFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public String getURLOfAPictureInGroup() {
		// TODO Auto-generated method stub
		return null;
	}

}
